#include "EntityPlayer.h"
#include "WorldModel.h"
#include "ProjectileManager.h"
#include "ExplosionManager.h"
#include "UserInterface.h"
#include "Sound.h"

CEntityPlayer::CEntityPlayer(int startPositionX, int startPositionY, int health, int speed, int state, 
							 int collisionCost, bool active, int indexAnimationUp, int indexAnimationLeft, 
							 int indexAnimationRight, int /*timeLastFrame*/):
			startPositionX(startPositionX), startPositionY(startPositionY), totalHealth(health), 
			state(state), indexAnimationUp(indexAnimationUp), indexAnimationLeft(indexAnimationLeft), 
			indexAnimationRight(indexAnimationRight), timeBetweenProjectile(500),
			timeCreationLastProjectile(0), timeLastFrame(-1),
			currentFrameAnimationLeft(-1), currentFrameAnimationRight(-1), currentFrameAnimationUp(-1),
			numberOfLife(3), beginTimeEntry(-1), endTimeEntry(-1),
			beginPositionEntryX(VIS.getScreenWidth()/2),beginPositionEntryY(VIS.getScreenHeight()+30),
			timeDisplayGameOver(3000), timeOfDeath(-1)
{
	assert(indexAnimationUp>=0);
	assert(indexAnimationLeft>=0);
	assert(indexAnimationRight>=0);

	this->speed=speed;
	this->currentPosX=-1;
	this->currentPosY=-1;
	this->previousPosX=0;
	this->previousPosY=0;
	
	this->currentHealth=health;
	this->collisionCost=collisionCost;
	this->active=active;
	this->side=eSidePlayer;
	
	this->collisionRectangle.setTop(0);
	this->collisionRectangle.setBottom(VIS.getAnimationHeight(this->indexAnimationLeft));
	this->collisionRectangle.setLeft(0);
	this->collisionRectangle.setRight(VIS.getAnimationWidth(this->indexAnimationLeft));
}

CEntityPlayer::~CEntityPlayer(void){}

void CEntityPlayer::update(void)
{
	if(this->currentHealth<=0) //if the player is dead
	{
		die();
	}
	else
	{
		if(this->state==eSpawn)
		{
			spawnPlayer();
			return;
		}

		this->previousPosX=this->currentPosX;
		this->previousPosY=this->currentPosY;

		//changing current position following the input
		if(USERINT.scanCode(HK_UP))
		{
			//if the player doesn't go out of the screen
			if(this->currentPosY>=speed)
			{
				this->currentPosY-=speed;
				state=CEntityPlayer::eFlyUp;
			}
		}
		if(USERINT.scanCode(HK_DOWN))
		{
			//if the player doesn't go out of the screen
			if(this->currentPosY+VIS.getAnimationHeight(this->indexAnimationUp)<VIS.getScreenHeight()-speed)
			{
				this->currentPosY+=speed;
				state=CEntityPlayer::eFlyDown;
			}
		}
		if(USERINT.scanCode(HK_LEFT))
		{
			//if the player doesn't go out of the screen
			if(this->currentPosX>=speed)
			{
				this->currentPosX-=speed;
				state=CEntityPlayer::eFlyLeft;
			}
		}
		if(USERINT.scanCode(HK_RIGHT))
		{
			//if the player doesn't go out of the screen
			if(this->currentPosX<=VIS.getScreenWidth()-speed-VIS.getAnimationWidth(this->indexAnimationUp))
			{
				this->currentPosX+=speed;
				state=CEntityPlayer::eFlyRight;
			}
		}
		if(!USERINT.scanCode(HK_UP) && !USERINT.scanCode(HK_DOWN) &&
			!USERINT.scanCode(HK_LEFT) && !USERINT.scanCode(HK_RIGHT))
		{
			state=CEntityPlayer::eFlyUp;
		}
		
		if(USERINT.scanCode('A') && USERINT.scanCode(HK_LEFT))
		{
			//spawn a projectile and play a sound
			if((int)HAPI->GetTime()>=timeCreationLastProjectile+timeBetweenProjectile)
			{
				PROJECTILEMANAGER.spawnProjectile(PROJECTILEMANAGER.getProjectileTemplate(eProjectileFireBallLeft),
					this->currentPosX,this->currentPosY);
				state=eFlyLeft;
				this->timeCreationLastProjectile=HAPI->GetTime();
				SOUND.stopSound(eSoundFireball);
				SOUND.playSound(eSoundFireball,eVolumeLow);
			}
		}
		else if(USERINT.scanCode('A') && USERINT.scanCode(HK_RIGHT))
		{
			//spawn a projectile and play a sound
			if((int)HAPI->GetTime()>=timeCreationLastProjectile+timeBetweenProjectile)
			{
				PROJECTILEMANAGER.spawnProjectile(PROJECTILEMANAGER.getProjectileTemplate(eProjectileFireBallRight),
					this->currentPosX,this->currentPosY);
				state=eFlyRight;
				this->timeCreationLastProjectile=HAPI->GetTime();
				SOUND.stopSound(eSoundFireball);
				SOUND.playSound(eSoundFireball,eVolumeLow);
			}
		}
		else if(USERINT.scanCode('A')||(USERINT.scanCode('A') && USERINT.scanCode(HK_UP))||
			(USERINT.scanCode('A') && USERINT.scanCode(HK_DOWN)))
		{
			//spawn a projectile and play a sound
			if((int)HAPI->GetTime()>=timeCreationLastProjectile+timeBetweenProjectile)
			{
				PROJECTILEMANAGER.spawnProjectile(PROJECTILEMANAGER.getProjectileTemplate(eProjectileFireBallUp),
					this->currentPosX,this->currentPosY);
				state=eFlyUp;
				this->timeCreationLastProjectile=HAPI->GetTime();
				SOUND.stopSound(eSoundFireball);
				SOUND.playSound(eSoundFireball,eVolumeLow);
			}
		}

		//test of collision
		checkCollision();
		if(this->currentHealth<=0)
		{
			die();
		}
	}
}
void CEntityPlayer::render(void)
{
	switch(this->state)
	{
		case CEntityPlayer::eFlyDown:
			VIS.displayAnimation(indexAnimationUp,this->currentPosX,this->currentPosY,&this->currentFrameAnimationUp, &this->timeLastFrame, true);
				break;
		case CEntityPlayer::eSpawn:
			VIS.displayAnimation(indexAnimationUp,this->currentPosX,this->currentPosY,&this->currentFrameAnimationUp, &this->timeLastFrame, true);
				break;
		case CEntityPlayer::eFlyUp:
			VIS.displayAnimation(indexAnimationUp,this->currentPosX,this->currentPosY, &this->currentFrameAnimationUp,&this->timeLastFrame,true);
				break;
		case CEntityPlayer::eFlyLeft:
			VIS.displayAnimation(indexAnimationLeft,this->currentPosX,this->currentPosY,&this->currentFrameAnimationLeft, &this->timeLastFrame,true);
			break;
		case CEntityPlayer::eFlyRight:
			VIS.displayAnimation(indexAnimationRight,this->currentPosX,this->currentPosY,&this->currentFrameAnimationRight,&this->timeLastFrame,true);
			break;
	}
}

void CEntityPlayer::die(void)
{
	this->numberOfLife--;

	//spawn an explosion and play a sound
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONDRAGON),
		this->currentPosX,this->currentPosY);
	SOUND.stopSound(eSoundExplosion);
	SOUND.playSound(eSoundExplosion,eVolumeHigh);

	if(numberOfLife>0)//if the player still got a live
	{
		this->state=eSpawn;
		this->currentHealth=this->totalHealth;
		this->currentPosX=beginPositionEntryX;
		this->currentPosY=beginPositionEntryY;
	}
	else //if not game over
	{
		this->state=eDead;
		this->currentPosX=700;
		this->currentPosY=700;
		this->active=false;
		return;
	}
}

void CEntityPlayer::spawnPlayer(void)
{
	//interpolation between beginPositionEntry and startPosition
	if(this->beginTimeEntry==-1)
	{
		this->beginTimeEntry=(float)HAPI->GetTime();
		this->endTimeEntry=this->beginTimeEntry+3000;
	}
	float s=((float)HAPI->GetTime()-beginTimeEntry)/(endTimeEntry-beginTimeEntry);
	this->currentPosX=(int)(beginPositionEntryX+s*(this->startPositionX-beginPositionEntryX));
	this->currentPosY=(int)(beginPositionEntryY+s*(this->startPositionY-beginPositionEntryY));

	//if the interpolation is over
	if(currentPosX==this->startPositionX || currentPosY<=this->startPositionY)
	{
		this->beginTimeEntry=-1;
		this->endTimeEntry=-1;
		this->state=eFlyUp;
	}
}
void CEntityPlayer::resetPlayer(void)
{
	currentHealth=100;
	numberOfLife=3;
	state=eSpawn;
	active=true;
}
bool CEntityPlayer::isDead(void)
{
	if(state==eDead)
	{
		return true;
	}
	return false;
}
void CEntityPlayer::checkCollision(void)
{
	CWorldEntity* collision=WMODEL.checkCollision(this);
	if(collision!=NULL) //if there is a collision
	{
		this->currentHealth-=collision->getCollisionCost();
		collision->setCurrentHealth(collision->getCurrentHealth()-this->collisionCost);
		currentPosX=previousPosX;
		currentPosY=previousPosY;
	}
	else
	{
		this->previousPosX=this->currentPosX;
		this->previousPosY=this->currentPosY;
	}
}
int CEntityPlayer::getStartPositionX(void) const
{
	return this->startPositionX;
}
int CEntityPlayer::getStartPositionY(void) const
{
	return this->startPositionY;
}
int CEntityPlayer::getState(void)
{
	return this->state;
}
int CEntityPlayer::getIndexAnimationUp(void)const
{
	return this->indexAnimationUp;
}
int CEntityPlayer::getIndexAnimationLeft(void)const
{
	return this->indexAnimationLeft;
}
int CEntityPlayer::getIndexAnimationRight(void)const
{
	return this->indexAnimationRight;
}
int CEntityPlayer::getTimeBetweenProjectile(void)const
{
	return this->timeBetweenProjectile;
}
int CEntityPlayer::getTimeCreationLastProjectile(void)const
{
	return this->timeCreationLastProjectile;
}
int CEntityPlayer::getCurrentFrameAnimationUp(void)const
{
	return this->currentFrameAnimationUp;
}
int CEntityPlayer::getCurrentFrameAnimationLeft(void)const
{
	return this->currentFrameAnimationLeft;
}
int CEntityPlayer::getCurrentFrameAnimationRight(void)const
{
	return this->currentFrameAnimationRight;
}
int CEntityPlayer::getTimeLastFrame(void)const
{
	return this->timeLastFrame;
}
int CEntityPlayer::getTotalHealth(void)
{
	return this->totalHealth;
}
int CEntityPlayer::getNumberOfLife(void)
{
	return this->numberOfLife;
}
void CEntityPlayer::setStartPositionX(int startPositionX)
{
	this->startPositionX=startPositionX;
}
void CEntityPlayer::setStartPositionY(int startPositionY)
{
	this->startPositionY=startPositionY;
}
void CEntityPlayer::setState(int state)
{
	this->state=state;
}
void CEntityPlayer::setIndexAnimationUp(int indexAnimationUp)
{
	this->indexAnimationUp=indexAnimationUp;
}
void CEntityPlayer::setIndexAnimationLeft(int indexAnimationLeft)
{
	this->indexAnimationLeft=indexAnimationLeft;
}
void CEntityPlayer::setIndexAnimationRight(int indexAnimationRight)
{
	this->indexAnimationRight=indexAnimationRight;
}
void CEntityPlayer::setTimeBetweenProjectile(int timeBetweenProjectile)
{
	this->timeBetweenProjectile=timeBetweenProjectile;
}
void CEntityPlayer::setTimeCreationLastProjectile(int timeCreationLastProjectile)
{
	this->timeCreationLastProjectile=timeCreationLastProjectile;
}
void CEntityPlayer::setCurrentFrameAnimationUp(int currentFrameAnimationUp)
{
	this->currentFrameAnimationUp=currentFrameAnimationUp;
}
void CEntityPlayer::setCurrentFrameAnimationLeft(int currentFrameAnimationLeft)
{
	this->currentFrameAnimationLeft=currentFrameAnimationLeft;
}
void CEntityPlayer::setCurrentFrameAnimationRight(int currentFrameAnimationRight)
{
	this->currentFrameAnimationRight=currentFrameAnimationRight;
}
void CEntityPlayer::setTimeLastFrame(int timeLastFrame)
{
	this->timeLastFrame=timeLastFrame;
}
void CEntityPlayer::setTotalHealth(int totalHealth)
{
	this->totalHealth=totalHealth;
}
void CEntityPlayer::setNumberOfLife(int numberOfLife)
{
	this->numberOfLife=numberOfLife;
}

